package com.luckberry.murder.controller;

import com.luckberry.murder.entity.Script;
import com.luckberry.murder.entity.User;
import com.luckberry.murder.entity.game.Appraise;
import com.luckberry.murder.entity.game.Game;
import com.luckberry.murder.entity.game.Participant;
import com.luckberry.murder.service.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Controller
public class PageController {

    @Resource
    private UserService userService;
    @Resource
    private GoodService goodService;
    @Resource
    private ScriptService scriptService;
    @Resource
    private NPCService npcService;
    @Resource
    private HouseService houseService;
    @Resource
    private GameService gameService;
    @Resource
    private OrderService orderService;

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView login(HttpSession session) {
        if (session.getAttribute("user") == null) {
            ModelAndView modelAndView = new ModelAndView("login");
            if (session.getAttribute("login_fail") != null) {
                modelAndView.getModel().put("login_fail", true);
                session.removeAttribute("login_fail");
            }
            return modelAndView;
        }
        return new ModelAndView("redirect:/index");
    }

    @RequestMapping(value = "/signup", method = RequestMethod.GET)
    public ModelAndView signup() {
        ModelAndView modelAndView = new ModelAndView("signup");
        modelAndView.getModel().put("perm", "user");
        return modelAndView;
    }

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public ModelAndView index(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        ModelAndView modelAndView = new ModelAndView("index");
        modelAndView.getModel().put("user", user);
        if (user.getPerm().equals("admin")) {
            modelAndView.getModel().put("user_count", userService.getUsers().size());
            modelAndView.getModel().put("script_count", scriptService.getScripts().size());
            modelAndView.getModel().put("good_count", goodService.getGoods().size());
            modelAndView.getModel().put("money_count", orderService.getOrders().stream()
                    .mapToDouble(order -> order.getCount() * order.getPrice())
                    .sum());
        } else {
            modelAndView.getModel().put("participant", gameService.getParticipantByUser(user.getUid()));
        }
        return modelAndView;
    }

    @RequestMapping(value = "/goods", method = RequestMethod.GET)
    public ModelAndView goods(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        ModelAndView modelAndView = new ModelAndView("goods");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("goods", goodService.getGoods());
        return modelAndView;
    }

    @RequestMapping(value = "/goods/name", method = RequestMethod.GET)
    public ModelAndView goodsByName(HttpSession session, String keyword) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        ModelAndView modelAndView = new ModelAndView("goods");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("goods", goodService.getGoodsByName(keyword));
        return modelAndView;
    }

    @RequestMapping(value = "/script", method = RequestMethod.GET)
    public ModelAndView scripts(HttpSession session, int sid) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        ModelAndView modelAndView = new ModelAndView("script");

        List<Appraise> appraises = gameService.getAppraisesBySid(sid);
        List<User> users = new ArrayList<>();
        appraises.forEach(appraise -> users.add(userService.getUser(appraise.getUid())));
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("script", scriptService.getScript(sid));
        modelAndView.getModel().put("npcs", npcService.getNPCByScript(sid));
        modelAndView.getModel().put("houses", houseService.getHousesByScript(sid));
        modelAndView.getModel().put("appraises", appraises);
        modelAndView.getModel().put("users", users);
        return modelAndView;
    }

    @RequestMapping(value = "/scripts", method = RequestMethod.GET)
    public ModelAndView scripts(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        ModelAndView modelAndView = new ModelAndView("scripts");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("scripts", scriptService.getScripts());
        return modelAndView;
    }

    @RequestMapping(value = "/scripts/name", method = RequestMethod.GET)
    public ModelAndView scripts(HttpSession session, String keyword) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        ModelAndView modelAndView = new ModelAndView("scripts");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("scripts", scriptService.getScriptsByName(keyword));
        return modelAndView;
    }

    @RequestMapping(value = "/game", method = RequestMethod.GET)
    public ModelAndView game(HttpSession session, int gid) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        Game game = gameService.getGame(gid);
        if (game == null) return new ModelAndView("redirect:/games");

        ModelAndView modelAndView = new ModelAndView("game");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("game", game);
        Script script = scriptService.getScript(game.getSid());
        modelAndView.getModel().put("script", script);
        modelAndView.getModel().put("house", houseService.getHouse(game.getHid()));
        modelAndView.getModel().put("end", Date.from(Instant.ofEpochMilli(game.getStart().getTime() + (long) 60 * 1000 * script.getTime())));
        List<User> players = new ArrayList<>();
        gameService.getParticipantsByGame(gid).forEach(participant -> {
            players.add(userService.getUser(participant.getUid()));
        });
        modelAndView.getModel().put("players", players);
        return modelAndView;
    }

    @RequestMapping(value = "/games", method = RequestMethod.GET)
    public ModelAndView games(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        ModelAndView modelAndView = new ModelAndView("games");

        List<Game> games = gameService.getGames();
        List<Script> scripts = new ArrayList<>();
        List<String> names = new ArrayList<>();
        games.forEach(game -> {
            scripts.add(scriptService.getScript(game.getSid()));
            names.add(userService.getUser(game.getUid()).getName());
        });

        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("games", games);
        modelAndView.getModel().put("names", names);
        modelAndView.getModel().put("scripts", scripts);
        return modelAndView;
    }

    @RequestMapping(value = "/create-game", method = RequestMethod.GET)
    public ModelAndView createGame(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        ModelAndView modelAndView = new ModelAndView("create-game");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("scripts", scriptService.getScripts());
        return modelAndView;
    }

    @RequestMapping(value = "/my_game", method = RequestMethod.GET)
    public ModelAndView myGame(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        Participant participant = gameService.getParticipantByUser(user.getUid());
        if (participant == null) return new ModelAndView("redirect:/create-game");
        Game game = gameService.getGame(participant.getGid());
        ModelAndView modelAndView = new ModelAndView("my_game");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("game", game);
        modelAndView.getModel().put("appraise", gameService.getAppraiseByUser(user.getUid()));
        if (game != null) {
            Script script = scriptService.getScript(game.getSid());
            modelAndView.getModel().put("script", script);
            modelAndView.getModel().put("house", houseService.getHouse(game.getHid()));
            modelAndView.getModel().put("end", Date.from(Instant.ofEpochMilli(game.getStart().getTime() + (long) 60 * 1000 * script.getTime())));
            List<User> players = new ArrayList<>();
            gameService.getParticipantsByGame(game.getGid()).forEach(part -> {
                players.add(userService.getUser(part.getUid()));
            });
            modelAndView.getModel().put("players", players);
        }
        return modelAndView;
    }

    @RequestMapping(value = "/help", method = RequestMethod.GET)
    public ModelAndView help(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:/login");
        ModelAndView modelAndView = new ModelAndView("help");
        modelAndView.getModel().put("user", user);
        return modelAndView;
    }
}
